{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e13c4e05",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "# data visualization\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "%matplotlib inline\n",
    "\n",
    "import tensorflow as tf\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from keras.models import Sequential\n",
    "from keras.layers import LSTM,Dense,Dropout\n",
    "from sklearn.metrics import mean_squared_error,mean_absolute_error,r2_score\n",
    "\n",
    "import math \n",
    "import os "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "473dbcd6",
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签\n",
    "plt.rcParams['axes.unicode_minus']=False #用来正常显示负号\n",
    "sns.set(font='SimHei')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d2de0223",
   "metadata": {},
   "outputs": [],
   "source": [
    "df= pd.read_csv('../dataset/sh600031.csv')  # 读取股票文件\n",
    "df.set_index('date',inplace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "fbe6b564",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>close</th>\n",
       "      <th>volume</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2003-07-03</th>\n",
       "      <td>23.00</td>\n",
       "      <td>23.00</td>\n",
       "      <td>20.10</td>\n",
       "      <td>21.30</td>\n",
       "      <td>33816715</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-04</th>\n",
       "      <td>21.30</td>\n",
       "      <td>22.18</td>\n",
       "      <td>21.05</td>\n",
       "      <td>21.84</td>\n",
       "      <td>7697544</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-07</th>\n",
       "      <td>21.90</td>\n",
       "      <td>21.96</td>\n",
       "      <td>21.51</td>\n",
       "      <td>21.80</td>\n",
       "      <td>3951205</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-08</th>\n",
       "      <td>21.80</td>\n",
       "      <td>22.22</td>\n",
       "      <td>21.70</td>\n",
       "      <td>21.91</td>\n",
       "      <td>2117357</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-09</th>\n",
       "      <td>21.75</td>\n",
       "      <td>22.65</td>\n",
       "      <td>21.70</td>\n",
       "      <td>22.47</td>\n",
       "      <td>3440447</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             open   high    low  close    volume\n",
       "date                                            \n",
       "2003-07-03  23.00  23.00  20.10  21.30  33816715\n",
       "2003-07-04  21.30  22.18  21.05  21.84   7697544\n",
       "2003-07-07  21.90  21.96  21.51  21.80   3951205\n",
       "2003-07-08  21.80  22.22  21.70  21.91   2117357\n",
       "2003-07-09  21.75  22.65  21.70  22.47   3440447"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbcb3585",
   "metadata": {},
   "source": [
    "## 数据检查"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0ab9bdc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function to check the missing percent of a DatFrame;\n",
    "def check_missing_data(df):\n",
    "    total = df.isnull().sum().sort_values(ascending = False)\n",
    "    percent = round(df.isnull().sum().sort_values(ascending = False) * 100 /len(df),2)\n",
    "    return pd.concat([total, percent], axis=1, keys=['Total','Percent'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e3ffd89f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Total</th>\n",
       "      <th>Percent</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>open</th>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>high</th>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>low</th>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>close</th>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>volume</th>\n",
       "      <td>0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        Total  Percent\n",
       "open        0      0.0\n",
       "high        0      0.0\n",
       "low         0      0.0\n",
       "close       0      0.0\n",
       "volume      0      0.0"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "check_missing_data(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d5b9fae7",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sns.heatmap(df.corr())\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "7b346f7f",
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "df.drop(['volume'],axis = 1,inplace= True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "46e00443",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>close</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2003-07-03</th>\n",
       "      <td>23.00</td>\n",
       "      <td>23.00</td>\n",
       "      <td>20.10</td>\n",
       "      <td>21.30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-04</th>\n",
       "      <td>21.30</td>\n",
       "      <td>22.18</td>\n",
       "      <td>21.05</td>\n",
       "      <td>21.84</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-07</th>\n",
       "      <td>21.90</td>\n",
       "      <td>21.96</td>\n",
       "      <td>21.51</td>\n",
       "      <td>21.80</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-08</th>\n",
       "      <td>21.80</td>\n",
       "      <td>22.22</td>\n",
       "      <td>21.70</td>\n",
       "      <td>21.91</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2003-07-09</th>\n",
       "      <td>21.75</td>\n",
       "      <td>22.65</td>\n",
       "      <td>21.70</td>\n",
       "      <td>22.47</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             open   high    low  close\n",
       "date                                  \n",
       "2003-07-03  23.00  23.00  20.10  21.30\n",
       "2003-07-04  21.30  22.18  21.05  21.84\n",
       "2003-07-07  21.90  21.96  21.51  21.80\n",
       "2003-07-08  21.80  22.22  21.70  21.91\n",
       "2003-07-09  21.75  22.65  21.70  22.47"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "630a42bb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.27901685 0.27674383 0.25182185 0.26343232]\n",
      " [0.2532241  0.2643365  0.26720643 0.27196583]\n",
      " [0.26232743 0.2610077  0.27465585 0.27133372]\n",
      " ...\n",
      " [0.27901685 0.27674383 0.28987852 0.28334382]\n",
      " [0.27218935 0.27507943 0.28599185 0.28603032]\n",
      " [0.27279624 0.275836   0.28971657 0.28223765]]\n"
     ]
    }
   ],
   "source": [
    "#获取DataFrame中的数据，形式为数组array形式\n",
    "values=df.values\n",
    "#确保所有数据为float类型\n",
    "values=values.astype('float32')\n",
    " \n",
    "# 特征的归一化处理\n",
    "scaler = MinMaxScaler(feature_range=(0, 1))\n",
    "scaled = scaler.fit_transform(values)\n",
    "print(scaled)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "d7576d76",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义series_to_supervised()函数\n",
    "# 将时间序列转换为监督学习问题\n",
    "def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):\n",
    "    \"\"\"\n",
    "    将时间序列框定为有监督的学习数据集。\n",
    "        论据：\n",
    "        数据：作为列表或NumPy数组的观察序列。\n",
    "        n_in：作为输入的滞后观测数（X）。\n",
    "        n_out：作为输出的观察数（y）。\n",
    "        dropnan：布尔值，决定是否删除具有NaN值的行。\n",
    "    返回：\n",
    "    pd.DataFrame(用于监督学习)\n",
    "    \"\"\"\n",
    "    n_vars = 1 if type(data) is list else data.shape[1]\n",
    "    df = pd.DataFrame(data)\n",
    "    cols, names = list(), list()\n",
    "    # input sequence (t-n, ... t-1)\n",
    "    for i in range(n_in, 0, -1):\n",
    "        cols.append(df.shift(i))\n",
    "        names += [('var%d(t-%d)' % (j + 1, i)) for j in range(n_vars)]\n",
    "    # forecast sequence (t, t+1, ... t+n)\n",
    "    for i in range(0, n_out):\n",
    "        cols.append(df.shift(-i))\n",
    "        if i == 0:\n",
    "            names += [('var%d(t)' % (j + 1)) for j in range(n_vars)]\n",
    "        else:\n",
    "            names += [('var%d(t+%d)' % (j + 1, i)) for j in range(n_vars)]\n",
    "    # put it all together\n",
    "    agg = pd.concat(cols, axis=1)\n",
    "    agg.columns = names\n",
    "    # drop rows with NaN values\n",
    "    if dropnan:\n",
    "        agg.dropna(inplace=True)\n",
    "    return agg"
   ]
  },
  {
   "cell_type": "raw",
   "id": "fd715bd0",
   "metadata": {},
   "source": [
    "该函数有四个参数：\n",
    "\n",
    "    data：输入数据需要是列表或二维的NumPy数组的观察序列。\n",
    "    n_in：输入的滞后观察数（X）。值可以在[1..len（data）]之间，可选的。默认为1。\n",
    "    n_out：输出的观察数（y）。值可以在[0..len（data）-1]之间，可选的。默认为1。\n",
    "    dropnan：Bool值，是否删除具有NaN值的行，可选的。默认为True。\n",
    "\n",
    "该函数返回一个值：\n",
    "\n",
    "    返回：用于监督学习的Pandas DataFrame。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "ce8fd25f",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "#将时间序列转换为监督学习问题\n",
    "reframed = series_to_supervised(scaled, 1, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "17b49a57",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>var1(t-1)</th>\n",
       "      <th>var2(t-1)</th>\n",
       "      <th>var3(t-1)</th>\n",
       "      <th>var4(t-1)</th>\n",
       "      <th>var1(t)</th>\n",
       "      <th>var2(t)</th>\n",
       "      <th>var3(t)</th>\n",
       "      <th>var4(t)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.279017</td>\n",
       "      <td>0.276744</td>\n",
       "      <td>0.251822</td>\n",
       "      <td>0.263432</td>\n",
       "      <td>0.253224</td>\n",
       "      <td>0.264336</td>\n",
       "      <td>0.267206</td>\n",
       "      <td>0.271966</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.253224</td>\n",
       "      <td>0.264336</td>\n",
       "      <td>0.267206</td>\n",
       "      <td>0.271966</td>\n",
       "      <td>0.262327</td>\n",
       "      <td>0.261008</td>\n",
       "      <td>0.274656</td>\n",
       "      <td>0.271334</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.262327</td>\n",
       "      <td>0.261008</td>\n",
       "      <td>0.274656</td>\n",
       "      <td>0.271334</td>\n",
       "      <td>0.260810</td>\n",
       "      <td>0.264942</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.273072</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.260810</td>\n",
       "      <td>0.264942</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.273072</td>\n",
       "      <td>0.260052</td>\n",
       "      <td>0.271448</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.281922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.260052</td>\n",
       "      <td>0.271448</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.281922</td>\n",
       "      <td>0.268851</td>\n",
       "      <td>0.275382</td>\n",
       "      <td>0.287449</td>\n",
       "      <td>0.284766</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   var1(t-1)  var2(t-1)  var3(t-1)  var4(t-1)   var1(t)   var2(t)   var3(t)  \\\n",
       "1   0.279017   0.276744   0.251822   0.263432  0.253224  0.264336  0.267206   \n",
       "2   0.253224   0.264336   0.267206   0.271966  0.262327  0.261008  0.274656   \n",
       "3   0.262327   0.261008   0.274656   0.271334  0.260810  0.264942  0.277733   \n",
       "4   0.260810   0.264942   0.277733   0.273072  0.260052  0.271448  0.277733   \n",
       "5   0.260052   0.271448   0.277733   0.281922  0.268851  0.275382  0.287449   \n",
       "\n",
       "    var4(t)  \n",
       "1  0.271966  \n",
       "2  0.271334  \n",
       "3  0.273072  \n",
       "4  0.281922  \n",
       "5  0.284766  "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reframed.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c1830e16",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>var1(t-1)</th>\n",
       "      <th>var2(t-1)</th>\n",
       "      <th>var3(t-1)</th>\n",
       "      <th>var4(t-1)</th>\n",
       "      <th>var4(t)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.279017</td>\n",
       "      <td>0.276744</td>\n",
       "      <td>0.251822</td>\n",
       "      <td>0.263432</td>\n",
       "      <td>0.271966</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.253224</td>\n",
       "      <td>0.264336</td>\n",
       "      <td>0.267206</td>\n",
       "      <td>0.271966</td>\n",
       "      <td>0.271334</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.262327</td>\n",
       "      <td>0.261008</td>\n",
       "      <td>0.274656</td>\n",
       "      <td>0.271334</td>\n",
       "      <td>0.273072</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.260810</td>\n",
       "      <td>0.264942</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.273072</td>\n",
       "      <td>0.281922</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.260052</td>\n",
       "      <td>0.271448</td>\n",
       "      <td>0.277733</td>\n",
       "      <td>0.281922</td>\n",
       "      <td>0.284766</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   var1(t-1)  var2(t-1)  var3(t-1)  var4(t-1)   var4(t)\n",
       "1   0.279017   0.276744   0.251822   0.263432  0.271966\n",
       "2   0.253224   0.264336   0.267206   0.271966  0.271334\n",
       "3   0.262327   0.261008   0.274656   0.271334  0.273072\n",
       "4   0.260810   0.264942   0.277733   0.273072  0.281922\n",
       "5   0.260052   0.271448   0.277733   0.281922  0.284766"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 删除不想预测的特征列，这里只预测收盘价\n",
    "# 所以删除的是var1(t),var2(t),var3(t),\n",
    "reframed.drop(['var1(t)','var2(t)','var3(t)'], axis=1, inplace=True)\n",
    "# 打印数据的前5行\n",
    "reframed.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aa1b3979",
   "metadata": {},
   "source": [
    "## 数据划分为训练集和测试集：\n",
    "\n",
    "* 将处理后的数据集划分为训练集和测试集。这里按0.85比例划分，将训练集和测试集的最终输入（X）转换为为LSTM的输入格式，即[samples,timesteps,features]。\n",
    "\n",
    "* Keras LSTM层的工作方式是通过接收3维（N，W，F）的数字阵列，其中N是训练序列的数目，W是序列长度，F是每个序列的特征数目。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "180008c8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3759, 1, 4) (3759,)\n",
      "(664, 1, 4) (664,)\n"
     ]
    }
   ],
   "source": [
    "# 划分训练集和测试集\n",
    "train = reframed.iloc[:int(len(reframed)*0.85),:].values\n",
    "test = reframed.iloc[int(len(reframed)*0.85):,:].values\n",
    "# 划分训练集和测试集的输入和输出\n",
    "train_X, train_y = train[:, :-1], train[:, -1]\n",
    "test_X, test_y = test[:, :-1], test[:, -1]\n",
    "#转化为三维数据\n",
    "# reshape input to be 3D [samples, timesteps, features]\n",
    "train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))\n",
    "test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))\n",
    "print(train_X.shape, train_y.shape)\n",
    "print(test_X.shape, test_y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b1dd2dc",
   "metadata": {},
   "source": [
    "# 模型构建及其预测"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "316b77a2",
   "metadata": {},
   "source": [
    "* 搭建LSTM模型并绘制损失图\n",
    "    * 本实验使用keras深度学习框架对模型进行快速搭建。建立Sequential模型，向其中添加LSTM层，设定Dropout为0.5，加入Dense层将其维度聚合为1，激活函数使用relu（也用了sigmoid作为激活函数，但实验效果不如relu），损失函数定为均方差Mean Absolute Error(MAE)。优化算法采用Adam，模型采用50个epochs并且每个batch的大小为100。其中：隐藏层有64个神经元，输出层1个神经元（回归问题），输入变量是一个时间步（t-1）的特征。在fit()函数中设置validation_data参数，记录训练集和测试集的损失。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01a4c60e",
   "metadata": {},
   "source": [
    "### 预测一次，并保存预测结构，用于之后的验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "a201d3e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "checkpoint_save_path = \"./checkpoint/test_1.ckpt\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "85c713fb",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,\n",
    "                                                 save_weights_only=True,\n",
    "                                                 save_best_only=True,\n",
    "                                                 monitor='val_loss')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "0f13a5ba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/50\n",
      "38/38 - 4s - loss: 0.1497 - val_loss: 0.0987 - 4s/epoch - 100ms/step\n",
      "Epoch 2/50\n",
      "38/38 - 0s - loss: 0.0871 - val_loss: 0.0396 - 383ms/epoch - 10ms/step\n",
      "Epoch 3/50\n",
      "38/38 - 0s - loss: 0.0363 - val_loss: 0.0239 - 294ms/epoch - 8ms/step\n",
      "Epoch 4/50\n",
      "38/38 - 0s - loss: 0.0162 - val_loss: 0.0110 - 275ms/epoch - 7ms/step\n",
      "Epoch 5/50\n",
      "38/38 - 0s - loss: 0.0157 - val_loss: 0.0152 - 262ms/epoch - 7ms/step\n",
      "Epoch 6/50\n",
      "38/38 - 0s - loss: 0.0151 - val_loss: 0.0118 - 266ms/epoch - 7ms/step\n",
      "Epoch 7/50\n",
      "38/38 - 0s - loss: 0.0152 - val_loss: 0.0116 - 308ms/epoch - 8ms/step\n",
      "Epoch 8/50\n",
      "38/38 - 0s - loss: 0.0148 - val_loss: 0.0116 - 267ms/epoch - 7ms/step\n",
      "Epoch 9/50\n",
      "38/38 - 0s - loss: 0.0139 - val_loss: 0.0114 - 251ms/epoch - 7ms/step\n",
      "Epoch 10/50\n",
      "38/38 - 0s - loss: 0.0139 - val_loss: 0.0101 - 267ms/epoch - 7ms/step\n",
      "Epoch 11/50\n",
      "38/38 - 0s - loss: 0.0143 - val_loss: 0.0082 - 323ms/epoch - 9ms/step\n",
      "Epoch 12/50\n",
      "38/38 - 0s - loss: 0.0132 - val_loss: 0.0091 - 235ms/epoch - 6ms/step\n",
      "Epoch 13/50\n",
      "38/38 - 0s - loss: 0.0128 - val_loss: 0.0091 - 279ms/epoch - 7ms/step\n",
      "Epoch 14/50\n",
      "38/38 - 0s - loss: 0.0127 - val_loss: 0.0081 - 268ms/epoch - 7ms/step\n",
      "Epoch 15/50\n",
      "38/38 - 0s - loss: 0.0123 - val_loss: 0.0098 - 258ms/epoch - 7ms/step\n",
      "Epoch 16/50\n",
      "38/38 - 0s - loss: 0.0133 - val_loss: 0.0095 - 269ms/epoch - 7ms/step\n",
      "Epoch 17/50\n",
      "38/38 - 0s - loss: 0.0120 - val_loss: 0.0088 - 287ms/epoch - 8ms/step\n",
      "Epoch 18/50\n",
      "38/38 - 0s - loss: 0.0123 - val_loss: 0.0084 - 290ms/epoch - 8ms/step\n",
      "Epoch 19/50\n",
      "38/38 - 0s - loss: 0.0122 - val_loss: 0.0083 - 264ms/epoch - 7ms/step\n",
      "Epoch 20/50\n",
      "38/38 - 0s - loss: 0.0120 - val_loss: 0.0081 - 305ms/epoch - 8ms/step\n",
      "Epoch 21/50\n",
      "38/38 - 0s - loss: 0.0117 - val_loss: 0.0083 - 246ms/epoch - 6ms/step\n",
      "Epoch 22/50\n",
      "38/38 - 0s - loss: 0.0118 - val_loss: 0.0089 - 269ms/epoch - 7ms/step\n",
      "Epoch 23/50\n",
      "38/38 - 0s - loss: 0.0117 - val_loss: 0.0091 - 242ms/epoch - 6ms/step\n",
      "Epoch 24/50\n",
      "38/38 - 0s - loss: 0.0118 - val_loss: 0.0120 - 260ms/epoch - 7ms/step\n",
      "Epoch 25/50\n",
      "38/38 - 0s - loss: 0.0123 - val_loss: 0.0084 - 278ms/epoch - 7ms/step\n",
      "Epoch 26/50\n",
      "38/38 - 0s - loss: 0.0121 - val_loss: 0.0103 - 242ms/epoch - 6ms/step\n",
      "Epoch 27/50\n",
      "38/38 - 0s - loss: 0.0116 - val_loss: 0.0080 - 284ms/epoch - 7ms/step\n",
      "Epoch 28/50\n",
      "38/38 - 0s - loss: 0.0110 - val_loss: 0.0080 - 227ms/epoch - 6ms/step\n",
      "Epoch 29/50\n",
      "38/38 - 0s - loss: 0.0109 - val_loss: 0.0102 - 236ms/epoch - 6ms/step\n",
      "Epoch 30/50\n",
      "38/38 - 0s - loss: 0.0110 - val_loss: 0.0085 - 256ms/epoch - 7ms/step\n",
      "Epoch 31/50\n",
      "38/38 - 0s - loss: 0.0118 - val_loss: 0.0163 - 224ms/epoch - 6ms/step\n",
      "Epoch 32/50\n",
      "38/38 - 0s - loss: 0.0120 - val_loss: 0.0083 - 233ms/epoch - 6ms/step\n",
      "Epoch 33/50\n",
      "38/38 - 0s - loss: 0.0112 - val_loss: 0.0135 - 231ms/epoch - 6ms/step\n",
      "Epoch 34/50\n",
      "38/38 - 0s - loss: 0.0113 - val_loss: 0.0111 - 262ms/epoch - 7ms/step\n",
      "Epoch 35/50\n",
      "38/38 - 0s - loss: 0.0117 - val_loss: 0.0210 - 316ms/epoch - 8ms/step\n",
      "Epoch 36/50\n",
      "38/38 - 0s - loss: 0.0120 - val_loss: 0.0081 - 296ms/epoch - 8ms/step\n",
      "Epoch 37/50\n",
      "38/38 - 0s - loss: 0.0108 - val_loss: 0.0109 - 222ms/epoch - 6ms/step\n",
      "Epoch 38/50\n",
      "38/38 - 0s - loss: 0.0111 - val_loss: 0.0100 - 224ms/epoch - 6ms/step\n",
      "Epoch 39/50\n",
      "38/38 - 0s - loss: 0.0114 - val_loss: 0.0177 - 220ms/epoch - 6ms/step\n",
      "Epoch 40/50\n",
      "38/38 - 0s - loss: 0.0118 - val_loss: 0.0081 - 289ms/epoch - 8ms/step\n",
      "Epoch 41/50\n",
      "38/38 - 0s - loss: 0.0107 - val_loss: 0.0105 - 257ms/epoch - 7ms/step\n",
      "Epoch 42/50\n",
      "38/38 - 0s - loss: 0.0109 - val_loss: 0.0101 - 236ms/epoch - 6ms/step\n",
      "Epoch 43/50\n",
      "38/38 - 0s - loss: 0.0111 - val_loss: 0.0189 - 218ms/epoch - 6ms/step\n",
      "Epoch 44/50\n",
      "38/38 - 0s - loss: 0.0114 - val_loss: 0.0087 - 247ms/epoch - 7ms/step\n",
      "Epoch 45/50\n",
      "38/38 - 0s - loss: 0.0109 - val_loss: 0.0145 - 228ms/epoch - 6ms/step\n",
      "Epoch 46/50\n",
      "38/38 - 0s - loss: 0.0110 - val_loss: 0.0114 - 253ms/epoch - 7ms/step\n",
      "Epoch 47/50\n",
      "38/38 - 0s - loss: 0.0117 - val_loss: 0.0217 - 234ms/epoch - 6ms/step\n",
      "Epoch 48/50\n",
      "38/38 - 0s - loss: 0.0119 - val_loss: 0.0078 - 267ms/epoch - 7ms/step\n",
      "Epoch 49/50\n",
      "38/38 - 0s - loss: 0.0112 - val_loss: 0.0107 - 230ms/epoch - 6ms/step\n",
      "Epoch 50/50\n",
      "38/38 - 0s - loss: 0.0110 - val_loss: 0.0116 - 221ms/epoch - 6ms/step\n"
     ]
    },
    {
     "data": {
      "image/png": "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XHLJJVx//fWtW8AE83q93HPPPYRCIcrKynj44YfJzMxs03Wu5fV6mTx5MmPGjGHFihWMHj2aiy66KCnqDnDXXXdx7rnn8pOf/IRbb72V6upqhg8fzp133tnaRWsRF198Menp6QCcddZZ3HzzzSdebyPJrVq1yrj66quNcDhsfP3118aDDz7Y2kVqUaFQyJgyZYrx05/+1Fi2bJlhGIZx8803G19++aURjUaNG2+80di3b18rlzKxXnvtNePDDz80DMMw/vOf/xi//vWv23yda61bt8747LPPDMMwjM2bNxs333xz0tT9ww8/NAYOHGj861//Mh566CHjtddeMwzDMO69915j1apVrVy6xCsoKDD+z//5P/VuS0S9k767aenSpUyYMAFN0xgxYgRr1qxp7SK1uCeeeIL+/fsDEIlE2LRpE+eddx6KonDOOefw7bfftnIJE+v666/n4osvBqCkpISMjIw2X+daAwYM4Mc//jHbt2/nr3/9K5deemlS1L2oqIiXXnqJa6+9FjD/zi+99FIAxowZw9dff92axWsRK1asYOPGjVx//fVcc801rF+/PiH1TvruJp/PR79+/QBQFIWqqqpWLlHL0nWdTp06xa77/X46duwYu56SkkJhYWFrFK3FlZaW8vLLL/Piiy+ybt262O1tuc61li9fTn5+Pk6nMyl+3g8//DBTp07lm2++AUBVVdxuN9B269ynTx9efvllsrOzWbFiBU8//XRC6p30IeF2u/H7/bHrXq+3FUtz8jkcDoLBYOy6z+fDaIO7x4dCIe6++27uvvtuOnXqlBR1ruu6667jRz/6EXfccQehUCh2e1us+/z58+nTpw/Dhg2LhYSu6xiGgaIo+Hy+Vi5hy+jVqxd2ux2A008/ne3bt5OamnrC9U767qbBgwezbNkyAPLz80lLS2vlEp1cmqaRmppKQUEBAN9//z1ZWVmtXKrEikQi3H333VxwwQVccMEFSVHnWvPnz+ePf/wjAGVlZaSlpbX5un/++eesXLmSnJwc3nnnHebOnUtJSQmrV68GYOPGjW2uzgCPPfYYS5cuBeCTTz6hf//+9OvX74TrnfQnHYpEIlx//fX079+fVatWceWVV7bp2R617r//fiZNmsTw4cP5/PPPef755znzzDNZsmQJCxcuxOVytXYRE+btt99m2rRpnHHGGQB06dKF8ePHt+k61woGg9x3330cOHAAm83Gww8/zM6dO5Oi7gB/+ctf6Nq1K3369OH3v/89o0eP5sMPP+Stt96q1+3aFuzbt4+77rqLqqoqOnbsyGOPPUZJSckJ1zvpQwLMP6Tc3FwyMjIYOnRoaxenVWzfvp3vv/+e8847j9TU1NYuzkmRjHWulYx137dvHytXrmTEiBH1xmXauhOtt4SEEEKIuJJ+TEIIIUR8EhJCCCHikpAQopUtXLiQhQsXtnYxhGiUhIQQQoi4kn4xnRDHw+/387vf/Y6SkhJOOeUU2rdvz9q1a6murqZ9+/Y899xz6LrOE088waZNm0hJSeGpp54iJSWFxx9/nE2bNmGxWHjuuecA2Lx5MzfccAPFxcXMnDmTU045pZVrKIRJWhJCHIe33nqLvn378vrrr1NUVMSWLVsYNmwYr732Gunp6fznP//hiy++IBAI8MYbb3DRRRfx4osvkpubSyQS4c033+Tmm2/m+++/B2D9+vW89NJL3HrrreTm5rZy7YQ4TFoSQhyHnTt38t133/Htt99SUVGB1Wrl6quvBuDUU09l3759RCIRBg0aBMDAgQP59NNPSU1NZcCAAQCMHTuWaDTKu+++y4QJE7BYLKSnp7N9+/ZWq5cQR5KWhBDHoVevXtx44428+uqr3HHHHXTu3Dm2aeDGjRvp3r07ffv2je0qvHbtWvr27Uvv3r1Zv349AO+//z6zZs0CzD20hPghkpaEEMfhqquuYurUqSxcuBC3203Pnj1Zv349OTk5dOjQgfPPPx9VVVmyZAnXXXddvTGJr776iuuvvx673c4zzzzDl19+2drVESIuWXEtRAL85S9/4eyzz2b48OGtXRQhEkpCQgghRFwyJiGEECIuCQkhhBBxSUgIIYSIS0JCCCFEXBISQggh4pKQEEIIEdf/B/Uw/Wt5sanUAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 搭建LSTM模型\n",
    "model = Sequential()\n",
    "model.add(LSTM(100, input_shape=(train_X.shape[1], train_X.shape[2])))\n",
    "model.add(Dropout(0.2))\n",
    "model.add(Dense(1,activation='relu'))\n",
    "model.compile(loss='mae', optimizer='adam')\n",
    "\n",
    "if os.path.exists(checkpoint_save_path + '.index'):\n",
    "    print('-------------load the model-----------------')\n",
    "    model.load_weights(checkpoint_save_path)\n",
    "    \n",
    "# fit network\n",
    "history = model.fit(train_X, train_y, epochs=50, batch_size=100, validation_data=(test_X, test_y), verbose=2,shuffle=False,\n",
    "                    validation_freq=1,callbacks=[cp_callback])\n",
    " \n",
    "# 绘制损失图\n",
    "plt.plot(history.history['loss'], label='train')\n",
    "plt.plot(history.history['val_loss'], label='test')\n",
    "plt.title('LSTM损失图', fontsize='12')\n",
    "plt.ylabel('loss', fontsize='10')\n",
    "plt.xlabel('epoch', fontsize='10')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2237a93a",
   "metadata": {},
   "source": [
    "* 预测并反转数据（反归一化）\n",
    "    * 需要将预测结果和测试集数据组合然后进行比例反转（invert the scaling），同时需要将测试集上的预期值也进行比例转换。 \n",
    "         这里为什么进行比例反转（反归一化）呢？（因为我们将原始数据进行了预处理（连同输出值y），此时的误差损失计算是在处理之后的数据上进行的，为了计算在原始比例上的误差需要将数据进行转化。反转时的矩阵大小一定要和原来的大小（shape）完全相同，否则就会报错。）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f4fbf850",
   "metadata": {},
   "outputs": [],
   "source": [
    "#模型预测收益率\n",
    "y_predict = model.predict(test_X)\n",
    "test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))\n",
    " \n",
    "# invert scaling for forecast\n",
    "#将预测结果按比例反归一化\n",
    "inv_y_test = np.concatenate((test_X[:, :3],y_predict), axis=1)\n",
    "inv_y_test = scaler.inverse_transform(inv_y_test)\n",
    "inv_y_predict=inv_y_test[:,-1]\n",
    " \n",
    "# invert scaling for actual\n",
    "#将真实结果按比例反归一化\n",
    "test_y = test_y.reshape((len(test_y), 1))\n",
    "inv_y_train = np.concatenate((test_X[:, :3],test_y), axis=1)\n",
    "inv_y_train = scaler.inverse_transform(inv_y_train)\n",
    "inv_y = inv_y_train[:, -1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "c855443c",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>反归一化后的预测结果</th>\n",
       "      <th>反归一化后的真实结果</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>11.651294</td>\n",
       "      <td>11.22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>11.449025</td>\n",
       "      <td>11.08</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>11.247650</td>\n",
       "      <td>11.18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>11.228152</td>\n",
       "      <td>11.76</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>11.716422</td>\n",
       "      <td>11.51</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   反归一化后的预测结果  反归一化后的真实结果\n",
       "0   11.651294       11.22\n",
       "1   11.449025       11.08\n",
       "2   11.247650       11.18\n",
       "3   11.228152       11.76\n",
       "4   11.716422       11.51"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = pd.DataFrame({\"反归一化后的预测结果\":inv_y_predict,'反归一化后的真实结果':inv_y})\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "1857da91",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(inv_y,color='red',label='Original')\n",
    "plt.plot(inv_y_predict,color='green',label='Predict')\n",
    "plt.xlabel('the number of test data')\n",
    "plt.ylabel('close')\n",
    "plt.title('预测与实际数据图')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "f473ea08",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "均方误差: 1.061497\n",
      "均方根误差: 1.030290\n",
      "平均绝对误差: 0.735911\n"
     ]
    }
   ],
   "source": [
    "from sklearn.metrics import mean_squared_error, mean_absolute_error\n",
    "# 评估\n",
    "# calculate MSE 均方误差 ---> E[(预测值-真实值)^2] (预测值减真实值求平方后求均值)\n",
    "mse = mean_squared_error(inv_y_predict, inv_y)\n",
    "# calculate RMSE 均方根误差--->sqrt[MSE]    (对均方误差开方)\n",
    "rmse = math.sqrt(mean_squared_error(inv_y_predict, inv_y))\n",
    "# calculate MAE 平均绝对误差----->E[|预测值-真实值|](预测值减真实值求绝对值后求均值）\n",
    "mae = mean_absolute_error(inv_y_predict, inv_y)\n",
    "print('均方误差: %.6f' % mse)\n",
    "print('均方根误差: %.6f' % rmse)\n",
    "print('平均绝对误差: %.6f' % mae)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "1c8b652a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "准确率：0.9717862901040871\n"
     ]
    }
   ],
   "source": [
    "#ACC\n",
    "error = 0\n",
    "summery = 0\n",
    "for i in range(24):\n",
    "    error += abs(inv_y_predict[i] - inv_y[i])\n",
    "    summery += inv_y[i]\n",
    "acc = 1 - error/summery\n",
    "print(\"准确率：{}\".format(acc))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep",
   "language": "python",
   "name": "deep"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
